﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace _3D_FileExplorer
{
    public class CreateGraphicsTree
    {
        public List<GraphicalNode> gTree = new List<GraphicalNode>();
        public static Dictionary<int, Dictionary<string, List<GraphicalNode>>> nodeTypes = new Dictionary<int, Dictionary<string, List<GraphicalNode>>>();
        private Matrix oRotation = Matrix.Identity;
        private Matrix oTranslation = Matrix.Identity;
        int branchLevel;
        long idn = 0;

        public CreateGraphicsTree(string root,Matrix oRotation, Matrix oTranslation, int branchLevel)
        {
            this.branchLevel = branchLevel;
            this.oRotation = oRotation;
            this.oTranslation = oTranslation;
            FileSystemDataProvider fdp = new FileSystemDataProvider();
            TreeCreator tc = new TreeCreator(fdp);
            List<Node> tree = tc.Build(root, branchLevel);
            //TreeConversion(gTree, ct.tree);
            TypeTreeConversion(gTree, tree);
            CalcualteBranchLevel(gTree, branchLevel);
            Rating ratingSum = CalculateWeight(gTree[0], new Rating(0,0));
            //Count parameters like number of files and number of dirs
            //gTree.Add(new GraphicalNode(root, true, 0, root, root));
            gTree[0].rotation *= Matrix.CreateRotationX(-MathHelper.PiOver2)*oRotation; //set clockwise rotation
            CalculateDirsFiles(gTree[0]);
            CalculateRadius(gTree[0],1,0,1);
            CalculateRotations(gTree[0]);
            CalculateBb(gTree);
            CalculateTranslations(gTree[0]);
            MultiTransform(gTree[0],oTranslation, 1);
        }
        #region Create GraphicalNode from Node
        private void TypeTreeConversion(List<GraphicalNode> gTree, List<Node> tree)
        {
            int id;
            int i;
            nodeTypes.Add(nodeTypes.Count, new Dictionary<string,List<GraphicalNode>>());
            id = nodeTypes.Count - 1;
            for(i = 0; i< tree.Count;i++)
            {
                if (tree[i] is LeafNode)
                {
                    if (nodeTypes[id].ContainsKey(tree[i].Type) == true)
                    {
                        nodeTypes[id][tree[i].Type].Add(new GraphicalNode(tree[i].Name, tree[i].Weight, tree[i].Type, tree[i].ShortName, tree[i].Description, idn));
                        idn += 1;
                    }
                    else
                    {
                        nodeTypes[id].Add(tree[i].Type, new List<GraphicalNode>());
                        nodeTypes[id][tree[i].Type].Add(new GraphicalNode(tree[i].Name, tree[i].Weight, tree[i].Type, tree[i].ShortName, tree[i].Description,idn));
                        idn += 1;
                        gTree.Add(new GraphicalNode(id.ToString(), tree[i].Weight, tree[i].Type, tree[i].ShortName, tree[i].Description,idn));
                        idn += 1;
                    }
                }
                else
                {
                    gTree.Add(new GraphicalNode(tree[i].Name,true,tree[i].Weight,tree[i].ShortName,tree[i].Description,idn));
                    idn += 1;
                    TypeTreeConversion(gTree[gTree.Count - 1].Branch, ((InnerNode)tree[i]).Branch);
                }
            }
        }

        public struct Rating
        {
            public float numFiles;
            public float rCount;
            public Rating(float numFiles, float rCount)
            {
                this.numFiles = numFiles;
                this.rCount = rCount;
            }
        }


        private Rating CalculateWeight(GraphicalNode branch,Rating rt)
        {
            int i = 0;
            Rating tempRat = new Rating(0, 0);
            for (i = 0; i < branch.Branch.Count; i++) //go deep into tree
            {
                if (branch.Branch[i].Dir == true)
                {
                    tempRat = CalculateWeight(branch.Branch[i],new Rating(0,0));
                    rt.numFiles += tempRat.numFiles;
                    rt.rCount += tempRat.rCount;
                }
                else
                {
                    rt.rCount += CaltulateNodeTypesRating(branch.Branch[i].Name, branch.Branch[i].Type).rCount;
                    rt.numFiles += CaltulateNodeTypesRating(branch.Branch[i].Name, branch.Branch[i].Type).numFiles;
                }
            }
            if ((branch.Dir == true)&&(rt.numFiles != 0))
            {
                branch.Weight = rt.rCount / rt.numFiles;
            }
            return rt;
        }

        private Rating CaltulateNodeTypesRating(string id, string type)
        {
            Rating tempRat;
             tempRat.numFiles= nodeTypes[int.Parse(id)][type].Count;
             tempRat.rCount = nodeTypes[int.Parse(id)][type].Count * nodeTypes[int.Parse(id)][type][0].Weight;
            return tempRat;
        }

        #endregion

        #region CALCULATIONS
        private void CalcualteBranchLevel(List<GraphicalNode> branch,int branchLevel)
        {
            int i;
            for(i = 0;i<branch.Count;i++)
            {
                if (branch[i].Dir == false)
                {
                    branch[i].Branchlevel = branchLevel;
                }
                else
                {
                    branch[i].Branchlevel = branchLevel;
                    CalcualteBranchLevel(branch[i].Branch,branchLevel-1);
                }

            }
        }
        private void CalculateDirsFiles(GraphicalNode branch)
        {
            foreach (GraphicalNode obj in branch.Branch)
            {
                if (obj.Dir == false)
                {
                    branch.FilesCount += 1;
                }
                else
                {
                    branch.DirCount += 1;
                    CalculateDirsFiles(obj);
                }

            }
        }
        #region BRANCH RADUIS
        private void CalculateRadius(GraphicalNode branch,float maxRadius,float min, float max)
        {
            float minRadius = maxRadius * Fe.par.radiusDifference; //xx% of maxRadius
            float onePercentFromWeight = (max-min)/100;
            float onePercentFromRadius = (maxRadius - minRadius)/100;
            if (max != min)
            {
                branch.Radius = ((branch.Weight - min) / onePercentFromWeight) * onePercentFromRadius + minRadius;
            }
            else
            {
                branch.Radius = maxRadius;
            }

            if (branch.Radius > 1)
            {
                branch.Radius = 1;
            }
            GetWeightLimits(branch,out min,out max); 
            foreach (GraphicalNode obj in branch.Branch)
            {
                if (obj.Dir == true)
                {
                    CalculateRadius(obj, branch.Radius * 0.9f, min, max);
                }
                else
                {
                    obj.cubeSide = branch.Radius;
                    obj.BbParametersMinus = new Vector3(-branch.Radius, -branch.Radius, -branch.Radius);
                    obj.BbParametersPlus = new Vector3(branch.Radius, branch.Radius, branch.Radius);
                }
            }

        }

        private void GetWeightLimits(GraphicalNode branch, out float min, out float max)
        {
            min = 2;
            max = 1;
            foreach (GraphicalNode br in branch.Branch)
            {
                if (br.Dir == true)
                {
                    if (br.Weight < min) min = br.Weight;
                    if (br.Weight > max) max = br.Weight;
                }
            }
        }

        #endregion
    
        #region ROTATIONS
        private void CalculateRotations(GraphicalNode branch)
        {
              int i;
              float j = 0;
              int counter = 0;
              for (i = 0; i < branch.Branch.Count; i++)
              {
                  if (branch.Branch[i].Dir == true)
                  {

                      if (branch.rotation.Up.X == 1.0f)
                      {

                          switch (counter)
                          {
                              case 0:
                                  branch.Branch[i].rotation = Y_plus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 1:
                                  branch.Branch[i].rotation = Z_plus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 2:
                                  branch.Branch[i].rotation = Y_minus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 3:
                                  branch.Branch[i].rotation = Z_minus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                          }
                      }
                      if (branch.rotation.Up.X == -1.0f)
                      {
                          switch (counter)
                          {
                              case 0:
                                  branch.Branch[i].rotation = Y_plus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 1:
                                  branch.Branch[i].rotation = Z_minus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 2:
                                  branch.Branch[i].rotation = Y_minus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 3:
                                  branch.Branch[i].rotation = Z_plus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                          }
                      }
                      if (branch.rotation.Up.Y == 1.0f)
                      {
                          switch (counter)
                          {
                              case 0:
                                  branch.Branch[i].rotation = X_plus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 1:
                                  branch.Branch[i].rotation = Z_minus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 2:
                                  branch.Branch[i].rotation = X_minus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 3:
                                  branch.Branch[i].rotation = Z_plus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                          }
                      }
                      if (branch.rotation.Up.Y == -1.0f)
                      {
                          switch (counter)
                          {
                              case 0:
                                  branch.Branch[i].rotation = X_plus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 1:
                                  branch.Branch[i].rotation = Z_plus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 2:
                                  branch.Branch[i].rotation = X_minus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 3:
                                  branch.Branch[i].rotation = Z_minus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                          }
                      }
                      if (branch.rotation.Up.Z == 1.0f)
                      {
                          switch (counter)
                          {
                              case 0:
                                  branch.Branch[i].rotation = Y_plus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 1:
                                  branch.Branch[i].rotation = X_plus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 2:
                                  branch.Branch[i].rotation = Y_minus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 3:
                                  branch.Branch[i].rotation = X_minus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                          }
                      }
                      if (branch.rotation.Up.Z == -1.0f)
                      {
                          switch (counter)
                          {
                              case 0:
                                  branch.Branch[i].rotation = Y_plus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 1:
                                  branch.Branch[i].rotation = X_minus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 2:
                                  branch.Branch[i].rotation = Y_minus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                              case 3:
                                  branch.Branch[i].rotation = X_plus(branch.Branch[i].rotation);
                                  counter++;
                                  break;
                          }
                      }
                      if (counter == 4) counter = 0;
               
                      CalculateRotations(branch.Branch[i]);
                  }
              }

        }

        private Matrix X_plus(Matrix rotation)
        {
            return rotation *= Matrix.CreateRotationZ(-MathHelper.PiOver2);
        }
        private Matrix X_minus(Matrix rotation)
        {
            return rotation *= Matrix.CreateRotationZ(MathHelper.PiOver2);
        }
        private Matrix Y_plus(Matrix rotation)
        {
            return rotation;
        }
        private Matrix Y_minus(Matrix rotation)
        {
            return rotation *= Matrix.CreateRotationZ(MathHelper.Pi);
        }
        private Matrix Z_plus(Matrix rotation)
        {
            return rotation *= Matrix.CreateRotationX(-MathHelper.PiOver2);
        }
        private Matrix Z_minus(Matrix rotation)
        {
            return rotation *= Matrix.CreateRotationX(MathHelper.PiOver2);
        }

        #endregion
        #region BASIC BOUDING BOXES
        private void CalculateBb(List<GraphicalNode> branch)  //create bounding box around each object
        {

            int i = 0;

            for (i = 0; i < branch.Count; i++)
            {
                if (branch[i].Dir == true) //directories
                {
                    switch(FindAxis(branch[i]))
                    {
                        case "X":
                            branch[i].BbParametersMinus = new Vector3(-branch[i].Radius, -branch[i].Radius, -branch[i].Radius);
                            branch[i].BbParametersPlus = new Vector3(branch[i].Radius*Fe.par.emptyBranchOverlap, branch[i].Radius, branch[i].Radius);
                            CalculateBb(branch[i].Branch);

                            break;
                        case "-X":
                            branch[i].BbParametersMinus = new Vector3(-branch[i].Radius * Fe.par.emptyBranchOverlap, -branch[i].Radius, -branch[i].Radius);
                            branch[i].BbParametersPlus = new Vector3(branch[i].Radius, branch[i].Radius, branch[i].Radius);
                            CalculateBb(branch[i].Branch);
                            break;
                        case "Y":
                            branch[i].BbParametersMinus = new Vector3(-branch[i].Radius, -branch[i].Radius, -branch[i].Radius);
                            branch[i].BbParametersPlus = new Vector3(branch[i].Radius, branch[i].Radius * Fe.par.emptyBranchOverlap, branch[i].Radius);
                            CalculateBb(branch[i].Branch);
                            break;
                        case "-Y":
                            branch[i].BbParametersMinus = new Vector3(-branch[i].Radius, -branch[i].Radius * Fe.par.emptyBranchOverlap, -branch[i].Radius);
                            branch[i].BbParametersPlus = new Vector3(branch[i].Radius, branch[i].Radius, branch[i].Radius);
                            CalculateBb(branch[i].Branch);
                            break;
                        case "Z":
                            branch[i].BbParametersMinus = new Vector3(-branch[i].Radius, -branch[i].Radius, -branch[i].Radius);
                            branch[i].BbParametersPlus = new Vector3(branch[i].Radius, branch[i].Radius, branch[i].Radius * Fe.par.emptyBranchOverlap);
                            CalculateBb(branch[i].Branch);
                            break;
                        case "-Z":
                            branch[i].BbParametersMinus = new Vector3(-branch[i].Radius, -branch[i].Radius, -branch[i].Radius * Fe.par.emptyBranchOverlap);
                            branch[i].BbParametersPlus = new Vector3(branch[i].Radius, branch[i].Radius, branch[i].Radius);
                            CalculateBb(branch[i].Branch);
                            break;
                    }
                }

            }
        }

        public string FindAxis(GraphicalNode branch)
        {
            if (branch.rotation.Up.X == 1f)
            {
                return "X";
            }
            if (branch.rotation.Up.X == -1f)
            {
                return "-X";
            }
            if (branch.rotation.Up.Y == 1f)
            {
                return "Y";
            }
            if (branch.rotation.Up.Y == -1f)
            {
                return "-Y";
            }
            if (branch.rotation.Up.Z == 1f)
            {
                return "Z";
            }
            if (branch.rotation.Up.Z == -1f)
            {
                return "-Z";
            }

            return null;
        }
        #endregion

        #region TRANSLATIONS
        private void CalculateTranslations(GraphicalNode branch)
        {
            int i = 0;
            bool branch_end = true;

            for (i = 0; i < branch.Branch.Count; i++) //go deep into tree
            {
                if (branch.Branch[i].Dir == true)
                {
                    CalculateTranslations(branch.Branch[i]);
                }
            }


            #region OTHER NODES
            #region X_AXIS;
            switch ((int)branch.rotation.Up.X)
            {
                case 1:
                    for (i = 0; i < branch.Branch.Count; i++)
                    {
                        //calculte branch X position and bb X dimensions
                        branch.Branch[i].translation *= Matrix.CreateTranslation(new Vector3(branch.BbParametersPlus.X + Math.Abs(branch.Branch[i].BbParametersMinus.X) + CalculateBasicSpace(i,branch.Branch[i]) , 0, 0)); //translate every folder
                        branch.BbParametersPlus += new Vector3((Math.Abs(branch.Branch[i].BbParametersMinus.X) + branch.Branch[i].BbParametersPlus.X) + CalculateBasicSpace(i, branch.Branch[i]), 0, 0); //set bb parameter+


                        //calculate another bb dimensions
                        switch ((int)branch.Branch[i].rotation.Up.Y)
                        {
                            case 1:
                                if (branch.BbParametersPlus.Y < branch.Branch[i].Height)
                                {
                                    branch.BbParametersPlus = new Vector3(branch.BbParametersPlus.X, branch.Branch[i].Height, branch.BbParametersPlus.Z);
                                }
                                break;
                            case -1:
                                if (branch.BbParametersMinus.Y > -branch.Branch[i].Height)
                                {
                                    branch.BbParametersMinus = new Vector3(branch.BbParametersMinus.X, -branch.Branch[i].Height, branch.BbParametersMinus.Z);
                                }
                                break;
                        }
                        switch ((int)branch.Branch[i].rotation.Up.Z)
                        {
                            case 1:
                                if (branch.BbParametersPlus.Z < branch.Branch[i].Height)
                                {
                                    branch.BbParametersPlus = new Vector3(branch.BbParametersPlus.X, branch.BbParametersPlus.Y, branch.Branch[i].Height);
                                }
                                break;
                            case -1:
                                if (branch.BbParametersMinus.Z > -branch.Branch[i].Height)
                                {
                                    branch.BbParametersMinus = new Vector3(branch.BbParametersMinus.X, branch.BbParametersMinus.Y, -branch.Branch[i].Height);
                                }
                                break;
                        }
                    }
                    branch.BbParametersPlus += new Vector3(branch.Radius, 0, 0); //ad one radius on the end
                    branch.BbParametersMinus += new Vector3(-branch.Radius, 0, 0); //ad one radius on the start
                    branch.Height = branch.BbParametersPlus.X; //set parrent height
                    break;
                case -1:
                    for (i = 0; i < branch.Branch.Count; i++)
                    {
                        //calculte branch -X position and bb X dimensions
                        branch.Branch[i].translation *= Matrix.CreateTranslation(new Vector3(branch.BbParametersMinus.X - branch.Branch[i].BbParametersPlus.X - CalculateBasicSpace(i, branch.Branch[i]), 0, 0)); //translate every folder
                        branch.BbParametersMinus += new Vector3(-(Math.Abs(branch.Branch[i].BbParametersMinus.X) + branch.Branch[i].BbParametersPlus.X) - CalculateBasicSpace(i, branch.Branch[i]), 0, 0); //set bb parameter-

                        //calculate another bb dimensions
                        switch ((int)branch.Branch[i].rotation.Up.Y)
                        {
                            case 1:
                                if (branch.BbParametersPlus.Y < branch.Branch[i].Height)
                                {
                                    branch.BbParametersPlus = new Vector3(branch.BbParametersPlus.X, branch.Branch[i].Height, branch.BbParametersPlus.Z);
                                }
                                break;
                            case -1:
                                if (branch.BbParametersMinus.Y > -branch.Branch[i].Height)
                                {
                                    branch.BbParametersMinus = new Vector3(branch.BbParametersMinus.X, -branch.Branch[i].Height, branch.BbParametersMinus.Z);
                                }
                                break;
                        }
                        switch ((int)branch.Branch[i].rotation.Up.Z)
                        {
                            case 1:
                                if (branch.BbParametersPlus.Z < branch.Branch[i].Height)
                                {
                                    branch.BbParametersPlus = new Vector3(branch.BbParametersPlus.X, branch.BbParametersPlus.Y, branch.Branch[i].Height);
                                }
                                break;
                            case -1:
                                if (branch.BbParametersMinus.Z > -branch.Branch[i].Height)
                                {
                                    branch.BbParametersMinus = new Vector3(branch.BbParametersMinus.X, branch.BbParametersMinus.Y, -branch.Branch[i].Height);
                                }
                                break;
                        }
                    }
                    branch.BbParametersPlus += new Vector3(branch.Radius, 0, 0); //ad one radius on the end
                    branch.BbParametersMinus += new Vector3(-branch.Radius, 0, 0); //ad one radius on the start
                    branch.Height = -branch.BbParametersMinus.X; //set parrent height
                    break;
            }
            #endregion
            #region Y_AXIS;
            switch ((int)branch.rotation.Up.Y)
            {
                case 1:
                    for (i = 0; i < branch.Branch.Count; i++)
                    {
                        //calculte branch Y position and bb Y dimensions
                        branch.Branch[i].translation *= Matrix.CreateTranslation(new Vector3(0, branch.BbParametersPlus.Y + Math.Abs(branch.Branch[i].BbParametersMinus.Y) + CalculateBasicSpace(i, branch.Branch[i]), 0)); //translate every folder
                        branch.BbParametersPlus += new Vector3(0, (Math.Abs(branch.Branch[i].BbParametersMinus.Y) + branch.Branch[i].BbParametersPlus.Y) + CalculateBasicSpace(i, branch.Branch[i]), 0); //set bb parameter+


                        //calculate another bb dimensions
                        switch ((int)branch.Branch[i].rotation.Up.X)
                        {
                            case 1:
                                if (branch.BbParametersPlus.X < branch.Branch[i].Height)
                                {
                                    branch.BbParametersPlus = new Vector3(branch.Branch[i].Height, branch.BbParametersPlus.Y, branch.BbParametersPlus.Z);
                                }
                                break;
                            case -1:
                                if (branch.BbParametersMinus.X > -branch.Branch[i].Height)
                                {
                                    branch.BbParametersMinus = new Vector3(-branch.Branch[i].Height, branch.BbParametersMinus.Y, branch.BbParametersMinus.Z);
                                }
                                break;
                        }
                        switch ((int)branch.Branch[i].rotation.Up.Z)
                        {
                            case 1:
                                if (branch.BbParametersPlus.Z < branch.Branch[i].Height)
                                {
                                    branch.BbParametersPlus = new Vector3(branch.BbParametersPlus.X, branch.BbParametersPlus.Y, branch.Branch[i].Height);
                                }
                                break;
                            case -1:
                                if (branch.BbParametersMinus.Z > -branch.Branch[i].Height)
                                {
                                    branch.BbParametersMinus = new Vector3(branch.BbParametersMinus.X, branch.BbParametersMinus.Y, -branch.Branch[i].Height);
                                }
                                break;
                        }
                    }
                    branch.BbParametersPlus += new Vector3(0, branch.Radius, 0); //ad one radius on the end
                    branch.BbParametersMinus += new Vector3(0, -branch.Radius, 0); //ad one radius on the start
                    branch.Height = branch.BbParametersPlus.Y; //set parent height
                    break;
                case -1:
                    for (i = 0; i < branch.Branch.Count; i++)
                    {
                        //calculte branch -Y position and bb Y dimensions
                        branch.Branch[i].translation *= Matrix.CreateTranslation(new Vector3(0, branch.BbParametersMinus.Y - branch.Branch[i].BbParametersPlus.Y - CalculateBasicSpace(i, branch.Branch[i]), 0)); //translate every folder
                        branch.BbParametersMinus += new Vector3(0, -(Math.Abs(branch.Branch[i].BbParametersMinus.Y) + branch.Branch[i].BbParametersPlus.Y) - CalculateBasicSpace(i, branch.Branch[i]), 0); //set bb parameter-

                        //calculate another bb dimensions
                        switch ((int)branch.Branch[i].rotation.Up.X)
                        {
                            case 1:
                                if (branch.BbParametersPlus.X < branch.Branch[i].Height)
                                {
                                    branch.BbParametersPlus = new Vector3(branch.Branch[i].Height, branch.BbParametersPlus.Y, branch.BbParametersPlus.Z);
                                }
                                break;
                            case -1:
                                if (branch.BbParametersMinus.X > -branch.Branch[i].Height)
                                {
                                    branch.BbParametersMinus = new Vector3(-branch.Branch[i].Height, branch.BbParametersMinus.Y, branch.BbParametersMinus.Z);
                                }
                                break;
                        }
                        switch ((int)branch.Branch[i].rotation.Up.Z)
                        {
                            case 1:
                                if (branch.BbParametersPlus.Z < branch.Branch[i].Height)
                                {
                                    branch.BbParametersPlus = new Vector3(branch.BbParametersPlus.X, branch.BbParametersPlus.Y, branch.Branch[i].Height);
                                }
                                break;
                            case -1:
                                if (branch.BbParametersMinus.Z > -branch.Branch[i].Height)
                                {
                                    branch.BbParametersMinus = new Vector3(branch.BbParametersMinus.X, branch.BbParametersMinus.Y, -branch.Branch[i].Height);
                                }
                                break;
                        }
                    }
                    branch.BbParametersPlus += new Vector3(0, branch.Radius, 0); //ad one radius on the end
                    branch.BbParametersMinus += new Vector3(0, -branch.Radius, 0); //ad one radius on the start
                    branch.Height = -branch.BbParametersMinus.Y; //set parent height
                    break;
            }
            #endregion
            #region Z_AXIS;
            switch ((int)branch.rotation.Up.Z)
            {
                case 1:
                    for (i = 0; i < branch.Branch.Count; i++)
                    {
                        //calculte branch Z position and bb Z dimensions
                        branch.Branch[i].translation *= Matrix.CreateTranslation(new Vector3(0, 0, branch.BbParametersPlus.Z + Math.Abs(branch.Branch[i].BbParametersMinus.Z) + CalculateBasicSpace(i, branch.Branch[i]))); //translate every folder
                        branch.BbParametersPlus += new Vector3(0, 0, (Math.Abs(branch.Branch[i].BbParametersMinus.Z) + branch.Branch[i].BbParametersPlus.Z) + CalculateBasicSpace(i, branch.Branch[i])); //set bb parameter+

                        //calculate another bb dimensions
                        switch ((int)branch.Branch[i].rotation.Up.X)
                        {
                            case 1:
                                if (branch.BbParametersPlus.X < branch.Branch[i].Height)
                                {
                                    branch.BbParametersPlus = new Vector3(branch.Branch[i].Height, branch.BbParametersPlus.Y, branch.BbParametersPlus.Z);
                                }
                                break;
                            case -1:
                                if (branch.BbParametersMinus.X > -branch.Branch[i].Height)
                                {
                                    branch.BbParametersMinus = new Vector3(-branch.Branch[i].Height, branch.BbParametersMinus.Y, branch.BbParametersMinus.Z);
                                }
                                break;
                        }
                        switch ((int)branch.Branch[i].rotation.Up.Y)
                        {
                            case 1:
                                if (branch.BbParametersPlus.Y < branch.Branch[i].Height)
                                {
                                    branch.BbParametersPlus = new Vector3(branch.BbParametersPlus.X, branch.Branch[i].Height, branch.BbParametersPlus.Z);
                                }
                                break;
                            case -1:
                                if (branch.BbParametersMinus.Y > -branch.Branch[i].Height)
                                {
                                    branch.BbParametersMinus = new Vector3(branch.BbParametersMinus.X, -branch.Branch[i].Height, branch.BbParametersMinus.Z);
                                }
                                break;
                        }
                    }
                    branch.BbParametersPlus += new Vector3(0, 0, branch.Radius); //ad one radius on the end
                    branch.BbParametersMinus += new Vector3(0, 0, -branch.Radius); //ad one radius on the start
                    branch.Height = branch.BbParametersPlus.Z; //set parent height
                    break;
                case -1:
                    for (i = 0; i < branch.Branch.Count; i++)
                    {
                        //calculte branch -Y position and bb Y dimensions
                        branch.Branch[i].translation *= Matrix.CreateTranslation(new Vector3(0, 0, branch.BbParametersMinus.Z - branch.Branch[i].BbParametersPlus.Z - CalculateBasicSpace(i, branch.Branch[i]))); //translate every folder
                        branch.BbParametersMinus += new Vector3(0, 0, -(Math.Abs(branch.Branch[i].BbParametersMinus.Z) + branch.Branch[i].BbParametersPlus.Z) - CalculateBasicSpace(i, branch.Branch[i])); //set bb parameter-

                        //calculate another bb dimensions
                        switch ((int)branch.Branch[i].rotation.Up.X)
                        {
                            case 1:
                                if (branch.BbParametersPlus.X < branch.Branch[i].Height)
                                {
                                    branch.BbParametersPlus = new Vector3(branch.Branch[i].Height, branch.BbParametersPlus.Y, branch.BbParametersPlus.Z);
                                }
                                break;
                            case -1:
                                if (branch.BbParametersMinus.X > -branch.Branch[i].Height)
                                {
                                    branch.BbParametersMinus = new Vector3(-branch.Branch[i].Height, branch.BbParametersMinus.Y, branch.BbParametersMinus.Z);
                                }
                                break;
                        }
                        switch ((int)branch.Branch[i].rotation.Up.Y)
                        {
                            case 1:
                                if (branch.BbParametersPlus.Y < branch.Branch[i].Height)
                                {
                                    branch.BbParametersPlus = new Vector3(branch.BbParametersPlus.X, branch.Branch[i].Height, branch.BbParametersPlus.Z);
                                }
                                break;
                            case -1:
                                if (branch.BbParametersMinus.Y > -branch.Branch[i].Height)
                                {
                                    branch.BbParametersMinus = new Vector3(branch.BbParametersMinus.X, -branch.Branch[i].Height, branch.BbParametersMinus.Z);
                                }
                                break;
                        }
                    }
                    branch.BbParametersPlus += new Vector3(0, 0, branch.Radius); //ad one radius on the end
                    branch.BbParametersMinus += new Vector3(0, 0, -branch.Radius); //ad one radius on the start
                    branch.Height = -branch.BbParametersMinus.Z; //set parent height
                    break;
            }
            #endregion
            #endregion

        }

        private float CalculateBasicSpace(int index, GraphicalNode branch)
        {
            float basicspace;
            if (branch.Dir == true)
            {
                basicspace = branch.Radius / Fe.par.spaceBetweenObjects;
            }
            else
            {
                basicspace = branch.cubeSide / Fe.par.spaceBetweenObjects;
            }
            if (index == 0) basicspace *= Fe.par.firstObjectOffset;
            return basicspace;
        }
        #endregion
        private void MultiTransform(GraphicalNode branch, Matrix translation, int oneTime) //set Branch position 
        {
            int i = 0;
            for (i = 0; i < branch.Branch.Count; i++)
            {
                branch.Branch[i].translation *= branch.translation * translation;
                if (branch.Branch[i].Dir == true)
                {
                    MultiTransform(branch.Branch[i], Matrix.Identity, 0);
                }
            }
            if (oneTime == 1)
            {
                branch.translation *= translation;
            }
        }

        #endregion
    }
}
